package kata04;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Kata0403 {

    //1.声明一个 参数类包装对象
    public static class DatInfo {

        private String result;

        private int firstNumber;

        private int secondNumber;

        public DatInfo() {
        }

        public DatInfo(String result, int firstNumber, int secondNumber) {
            this.result = result;
            this.firstNumber = firstNumber;
            this.secondNumber = secondNumber;
        }

        /**
         *  1.1. 定义获取 差集 方法
         * @return 差集(取正数)
         */
        public int getDiffNumber(){
            return Math.abs(this.firstNumber - this.secondNumber);
        }

        public String getResult() {
            return result;
        }

        public void setResult(String result) {
            this.result = result;
        }

        public int getFirstNumber() {
            return firstNumber;
        }

        public void setFirstNumber(int firstNumber) {
            this.firstNumber = firstNumber;
        }

        public int getSecondNumber() {
            return secondNumber;
        }

        public void setSecondNumber(int secondNumber) {
            this.secondNumber = secondNumber;
        }
    }

    //2.文件数据读取 抽象类
    public static abstract class AbstractDatFileReader{

        //2.1 通过字符串 获取 字符串数组 (子类重写)
        abstract String[] getStrArray(String strLine);

        //2.2 验证是否合法(子类重写)
        abstract boolean verify(List<String> innerList);

        //2.3 赋值 DatInfo(子类重写)
        abstract DatInfo setDatInfo(List<String> innerList);

        //2.4  获取 DatInfo 列表  通过读取文件的方式
        public List<DatInfo> getDataList(String path){
            try(BufferedReader br = new BufferedReader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(path), "UTF-8"))) {
                String strLine;
                List<DatInfo> datInfos = new ArrayList<>();
                DatInfo datInfo;
                while ((strLine = br.readLine()) != null) {
                    //调用子类方法获取 数组
                    String[] strArray = getStrArray(strLine);
                    //数组不为空 并且长度大于0
                    if(strArray != null && strArray.length > 0){
                        //去掉数组中空格
                        List<String> innerList = Stream.of(strArray).filter(innerStr -> {
                            return innerStr.trim().length() > 0;
                        }).collect(Collectors.toList());

                        //验证合法
                        if(verify(innerList)){
                            //合法后，将数据写入列表
                            datInfos.add(setDatInfo(innerList));
                        }
                    }
                }
                return datInfos;
            }catch (IOException e){
                e.printStackTrace();
            }
            return null;
        }

        public boolean isNumeric(String str){
            Pattern pattern = Pattern.compile("[0-9]*");
            Matcher isNum = pattern.matcher(str);
            if( !isNum.matches() ){
                return false;
            }
            return true;
        }

        public int getNumber(String str){
            str = str.trim();
            try {
                return Integer.valueOf(str);
            } catch (NumberFormatException e) {
                return Integer.valueOf(str.substring(0, str.length()-1));
            }
        }
    }


    //3.定义 气象数据读取实现类 继承文件数据读取抽象类
    public static class WeatherDatFileReader extends AbstractDatFileReader{

        @Override
        String[] getStrArray(String strLine) {
            if(strLine != null && strLine.length() > 0){
                return strLine.split(" ");
            }
            return null;
        }

        @Override
        boolean verify(List<String> innerList) {
            if(innerList != null && innerList.size() > 0){
                return isNumeric(innerList.get(0));
            }
            return false;
        }

        @Override
        DatInfo setDatInfo(List<String> innerList) {
            return new DatInfo(innerList.get(0),getNumber(innerList.get(1)),getNumber(innerList.get(2)));
        }
    }

    //4.定义 足球数据读取实现类 继承文件数据读取抽象类
    public static class FootballDatFileReader extends AbstractDatFileReader{

        @Override
        String[] getStrArray(String strLine) {
            if(strLine != null && strLine.length() > 0){
                strLine = strLine.replaceAll("-","");
                if(strLine.trim().length() > 0){
                    return strLine.split(" ");
                }
            }
            return null;
        }

        @Override
        boolean verify(List<String> innerList) {
            if(innerList != null && innerList.size() > 0){
                if(innerList.size() == 9 && isNumeric(innerList.get(6)) && isNumeric(innerList.get(7))){
                    return true;
                }
            }
            return false;
        }

        @Override
        DatInfo setDatInfo(List<String> innerList) {
            return new DatInfo(innerList.get(1),getNumber(innerList.get(6)),getNumber(innerList.get(7)));
        }
    }


    //5.定义一个结果处理类
    public static class DiffMinDatInfo{

        private final AbstractDatFileReader datFileReader;

        private final String path;

        public DiffMinDatInfo(AbstractDatFileReader datFileReader,String path) {
            this.datFileReader = datFileReader;
            this.path = path;
        }

        /**
         * 获取结果
         * @return resultInfo.result
         */
        public String getDiffMinResult() {
            List<DatInfo> dataList = datFileReader.getDataList(path);
            if(dataList != null && dataList.size() > 0){
                DatInfo resultInfo = dataList.get(0);
                for (DatInfo info : dataList) {
                    if(resultInfo.getDiffNumber() > info.getDiffNumber()){
                        resultInfo = info;
                    }
                }
                return resultInfo.getResult();
            }
            return "";
        }
    }

}
